package testing;

import static org.junit.Assert.*;
import hypeerweb.HyPeerWeb;
import hypeerweb.node.Contents;
import hypeerweb.node.Node;


import org.junit.Test;

import hypeerweb.visitor.*;

public class BroadcastVisitorTest {

	@Test
	public void blackboxTest(){
		
		HyPeerWeb hw = createHyPeerWebWith(10);
		doBroadcast(hw.getNode(9));
		assertTrue(assertOneVisitPerNode(hw));
		
		
		hw = createHyPeerWebWith(8);
		doBroadcast(hw.getNode(7));
		assertTrue(assertOneVisitPerNode(hw));
				
		hw = createHyPeerWebWith(1);
		doBroadcast(hw.getNode(0));
		assertTrue(assertOneVisitPerNode(hw));
				
		hw = createHyPeerWebWith(10000);
		doBroadcast(hw.getNode(999));
		assertTrue(assertOneVisitPerNode(hw));
		
		hw = createHyPeerWebWith(10000);
		doBroadcast(hw.getNode(18));
		assertTrue(assertOneVisitPerNode(hw));
				
		hw = createHyPeerWebWith(10000);
		doBroadcast(hw.getNode(19));
		assertTrue(assertOneVisitPerNode(hw));
		
		hw = createHyPeerWebWith(10000);
		doBroadcast(hw.getNode(20));
		assertTrue(assertOneVisitPerNode(hw));
		
		hw = createHyPeerWebWith(16);
		doBroadcast(hw.getNode(15));
		assertTrue(assertOneVisitPerNode(hw));
		
		hw = createHyPeerWebWith(16);
		doBroadcast(hw.getNode(14));
		assertTrue(assertOneVisitPerNode(hw));
		
		
		Node n0 = new Node(0);
		hw = createHyPeerWebWith(16);
		doBroadcast(n0);
		assertTrue(!assertOneVisitPerNode(hw));
		
		//invalid
		
//		BroadcastHelper helpVisitor = new BroadcastHelper(new BroadcastVisitor());
//		doBroadcastInvalid(hw.getNode(0));
	}
	
	
	
	
	
	private HyPeerWeb createHyPeerWebWith(int numberOfNodes) {
		HyPeerWeb hypeerweb = HyPeerWeb.getSingleton();
		hypeerweb.clear();
		Node node0 = new Node(0);
		hypeerweb.addToHyPeerWeb(node0, null);

		for (int i = 1; i < numberOfNodes; i++) {
			Node node = new Node(0);
			node0.addToHyPeerWeb(node);
		}
		
		return hypeerweb;
	}
	
	
	public void doBroadcast(Node start) {
		BroadcastHelper helpVisitor = new BroadcastHelper(new BroadcastVisitor() {
			
			private int visits = 0;
			
			@Override
			protected void operation(Node node, Parameters parameters) {
                int pos = 0;
                if (parameters.get("COUNTER_KEY") != null) {
                        pos = (int)(Integer)parameters.get("COUNTER_KEY");
                }
                node.getContents().set("COUNTER_KEY", pos);
               
                parameters.set("COUNTER_KEY", ++pos);
			}
			
		});
		
		start.accept(helpVisitor, SendVisitor.createInitialParameters(0));
	}
	public void doBroadcastInvalid(Node start) {
		BroadcastHelper helpVisitor = new BroadcastHelper(new BroadcastVisitor() {
			@Override
			protected void operation(Node node, Parameters parameters) {
			}
		});

		
		Parameters p = SendVisitor.createInitialParameters(0);

		//invalid inputs
//		start.accept(helpVisitor, null);
//		helpVisitor.visit(null, null);
//		helpVisitor.visit(start, null);
//		helpVisitor.visit(null, p);
//		
		Parameters p1 = SendVisitor.createInitialParameters(10001);
		helpVisitor.visit(start,p1);
		
		
	}
	
	
	public boolean assertOneVisitPerNode(HyPeerWeb hw){
		int expectedSum = 0;
		int sum = 0;
		for(int i = 0; i<hw.size(); i++){
			expectedSum += i;
			Node n = hw.getNode(i);
			if(n.getContents().containsKey("COUNTER_KEY"))
				sum+=(int)(Integer)n.getContents().get("COUNTER_KEY");
		}
		if(expectedSum==sum){
			return true;
		}
		else
			return false;
//		assertTrue(expectedSum==sum);
		
//		doBroadcast(hw.getNode(0));
	}
	
}
